ICTSC2018 本戦 問題解説: 研修できひんやんけ!

問題文

ここに以前新入社員が作ったXenサーバーと、業務での検証用のVMがあります。

今年の新入社員に、Xenサーバーに入っているVMの更新を依頼し、作業を行ってもらっていましたが、

アップデートを行い再起動をしたらVMがインターネットに接続できなくなったと連絡を受けました。

このサーバーは今日は使用しませんが、新入社員の明後日以降の実習環境になるため、それまでに復旧させなければならず、

また、あなたは明日予定があり早く退社しなければならず、

明日の業務終了時間である日曜日の15:00(コンテスト終了時間)までに復旧させる必要があります。

また、新入社員の研修を兼ねているため、メンターであるあなたは今年の新入社員に「なぜダメだったのか」を説明する必要があり、

新入社員の教育につなげる必要があります。

このVMがインターネットに接続できない原因を突き止め、起動させてください。

また、その原因を説明してください。

情報

Xenの動いているサーバー

IPアドレス: 192.168.5.1

ユーザー: admin

パスワード: xenhost

OS: Ubuntu 18.04 ( Xen Hypervisor Kernel )

Xen上のゲストVM

IPアドレス: 192.168.5.100

ユーザー: root

パスワード: なし

OS: ArchLinux ( Para-Virtualization )

SSHサーバーは動作していません。ping疎通ができればOKです。

構成

UbuntuがDom-0として稼働し、ArchLinuxがDom-Uとして稼働していた

解説

この問題はXenサーバのカーネルに原因があり発生していました。
仮想マシンが使用しているカーネルのバージョンと、Xenサーバ側が仮想マシンの起動に指定しているカーネルのバージョンが一致していません。その状態でも仮想マシンの起動はできるのですが、Xenサーバが指定したカーネルのネットワークモジュールが見つからないためNICを認識せず、外部と通信できません。

解決方法は以下の3つがあります。未完

  1. arch.cfgに `bootloader = “pygrub”` を追加しkernel, ramdiskとextraを消してarchを起動
  2. ゲストマシン上で動作しているvmlinuz-linuxとinitramfs-linux.imgをXenサーバにコピーし、それを使って起動させる
  3. Xenサーバのキャッシュから圧縮されたカーネルを解凍しそれを使って起動させる

それぞれについて解説をしていきます。

まず1つ目は 起動する際に使用するDomain-Uの設定ファイルである arch.cfg に以下の操作をします。
bootloader = "pygrub" を追加
– kernel, ramdiskとextraの行を削除
その後、編集後のファイルを使って sudo xl create arch.cfg を実行し仮想マシンを起動します。そうすると起動時に仮想マシンのディスクに設置してあるブートローダーであるgrubの設定ファイルを読み、ゲストの起動時に「ゲストのディスクに実際にインストールされたカーネル」で起動することができます。
その結果、正しいカーネルモジュールを使用することができるようになり、NICが認識され外部と通信できるようになります。

編集前

name = "arch"
kernel = "/guest/vmlinuz-linux"
ramdisk = "/guest/initramfs-linux.img"
extra = "root=UUID=24225d68-7d38-41fa-b8b5-d8b6c7cfa3b9 rw"
memory = 768
hostname = "arch"
disk =  [ "phy:/guest/arch.img,xvda,w" ]
vif = [ 'mac=00:16:3e:00:00:01,bridge=xenbr0,vifname=arch' ]

編集後

name = "arch"
bootloader = "pygrub"
memory = 768
hostname = "arch"
disk =  [ "phy:/guest/arch.img,xvda,w" ]
vif = [ 'mac=00:16:3e:00:00:01,bridge=xenbr0,vifname=arch' ]

2つめは、動作している仮想マシンのディスクをXenサーバ側にマウントし、仮想マシンのカーネルをXenサーバにコピーします。仮想マシンのカーネルを使用して起動することでNICが認識され外部と通信が可能になります。以下のコマンドを順に実行すると、起動した仮想マシンがNICを認識し外部と通信が可能となります。

<br />[Xenサーバ]$ sudo mount -t ext4 -o loop,offset=1048576 /guest/arch.img /mnt

[Xenサーバ]$ sudo cp /mnt/boot/vmlinuz-linux /guest/

[Xenサーバ]$ sudo cp /mnt/boot/initramfs-linux.img /guest/

[Xenサーバ]$ sudo xl create -c arch.cfg

3つめは仮想マシン内にXenサーバが指定しているバージョンのカーネルが残っていました。それを使って起動すると同様にNICが認識され外部と通信が可能になります。以下にカーネルのバージョンを合わせて起動するコマンドを記載します。

<br />[仮想マシン]# pacman -U /var/cache/pacman/pkg/linux-4.19.1.arch1-1-x86_64.pkg.tar.xz

[仮想マシン]# reboot

講評

この問題の解答を提出した8チームのうち完全解答したチームは4チームでした。私の想定では3つの想定解のうち1個目の pygrub で解いて、他の解答はしてこないだろうと思っていたら完全解答した4チーム全てが pygrub を使わずに来たので驚きました。さらに1チームだけ仮想マシン内のキャッシュから起動させていたのでよく気づいたなと思いました。

解答数が少なかったので難しすぎたかなと思いましたが、完全解答したチームはすごいなと思いました。

ちなみに

カーネルのバージョンはfileコマンドで確認することもできます。